package com.bodgittandscarper.brokerhmi.view;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingWorker;
import javax.swing.text.MaskFormatter;

import suncertify.db.RecordNotFoundException;

import com.bodgittandscarper.broker.types.Record;
import com.bodgittandscarper.brokerhmi.control.BASControl;
import com.bodgittandscarper.brokerhmi.model.HMIModel;
import com.bodgittandscarper.brokerhmi.model.ObservableEvent;
import com.bodgittandscarper.brokerhmi.model.PropertyListener;

/**
 * View class holding book panel elements. 
 * 
 * @author Morten Rummelhoff
 *
 */
public class BookPanel implements PropertyListener {

	
	Logger log = Logger.getLogger(getClass().getName());

	private BASControl basControl;
	private HMIModel hmiModel;

	private JPanel bookRecordPanel;
	
	private JToggleButton lockRecordButton;
	private JButton applyButton;
	private JButton cancelButton;
	
	private JFormattedTextField ownerTextField;
	
	private Record selectedRecord;
	
	
	public BookPanel(HMIModel hmiModel, BASControl basControl) {
	
		this.hmiModel = hmiModel;
		this.basControl = basControl;

		createGUI();

		this.hmiModel.addPropertyListener(this);

	}
	
	@Override
	public void propertyChanged(ObservableEvent event, Object value) {
		
		if (event == ObservableEvent.SELECT_RECORD_CHANGED) {
			selectedRecord = (Record) value;
			//update owner textfield with selected value
			if (selectedRecord != null)
				ownerTextField.setText(selectedRecord.getRecordFields()[5].trim());
			
		} 
		else if (event == ObservableEvent.LOCKRECORD_BUTTON_CHANGED) {
			applyButton.setEnabled(lockRecordButton.isSelected());
			cancelButton.setEnabled(lockRecordButton.isSelected());
			ownerTextField.setEditable(lockRecordButton.isSelected());
			ownerTextField.setEnabled(lockRecordButton.isSelected());
			
		}
		else if (event == ObservableEvent.SELECTED_RECORD_ALREADY_LOCKED) {
			applyButton.setEnabled(false);
			cancelButton.setEnabled(false);
			ownerTextField.setEditable(false);
			ownerTextField.setEnabled(false);
		}
		
		lockRecordButton.setEnabled(selectedRecord != null && 
				event != ObservableEvent.SELECTED_RECORD_ALREADY_LOCKED);
			
	}

	
	private void createGUI() {

		bookRecordPanel = new JPanel();
		bookRecordPanel.setLayout(new BoxLayout(bookRecordPanel, BoxLayout.Y_AXIS));
		bookRecordPanel.setBorder(BorderFactory.createTitledBorder("Book Record"));


		JPanel horizontalPanel = new JPanel();
		horizontalPanel.setLayout(new GridBagLayout());

		GridBagConstraints gbc = new GridBagConstraints();
		gbc.anchor = GridBagConstraints.WEST;
		gbc.ipady = 2;	
		gbc.insets = new Insets(2, 2, 2, 2);

		gbc.gridy++;

		gbc.gridx = 0;
		horizontalPanel.add(new JLabel("Owner"), gbc);
		gbc.gridx = 1;
		try {
			ownerTextField = new JFormattedTextField(new MaskFormatter("########"));
		} catch (ParseException e3) {
			//ignore
		}
		ownerTextField.setFocusLostBehavior(JFormattedTextField.COMMIT);
		ownerTextField.setColumns(10);
		ownerTextField.setEnabled(false);
		horizontalPanel.add(ownerTextField, gbc);
		
		//buttonpanel
		JPanel buttonPanel = new JPanel();
		lockRecordButton = new JToggleButton("Lock");
		lockRecordButton.setEnabled(false);
		lockRecordButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				
				if (lockRecordButton.isSelected()) {
					hmiModel.notifyPropertyChange(ObservableEvent.STATUS_TEXT_CHANGED, 
							"Locking Record: '" + selectedRecord.getRecordFields()[0].trim() + "'. Locked by another user. Waiting." );
					hmiModel.notifyPropertyChange(ObservableEvent.SELECTED_RECORD_ALREADY_LOCKED, null);
				}
				
				//Use the SwingWorker to avoid blocking the EDT when invoking remote objects methods.  
				new SwingWorker<String, Object>() {
					
					private String result;
					
					@Override
					protected String doInBackground() {
						try {
							if (lockRecordButton.isSelected()) {
								basControl.lockRecord(selectedRecord.getRecordNumber());
								result = "Record: '" + selectedRecord.getRecordFields()[0].trim() + "' locked. Ready to update.";
							}
							else {
								basControl.unlockRecord(selectedRecord.getRecordNumber());
								result = "Unlocked Record: '" + selectedRecord.getRecordFields()[0].trim() +"'";
							}
						} catch (RemoteException e) {
							result = "Unable to Lock/Unlock record: " + selectedRecord.getRecordNumber() +
							" . Cause: " + e.getMessage();
						} catch (RecordNotFoundException ee) {
							result = "Unable to Lock/Unlock record: " + selectedRecord.getRecordNumber() + 
							". Record does not exist. " + ee.getMessage();
						}

						return result;
					}

					@Override
					protected void done() {												
						hmiModel.notifyPropertyChange(ObservableEvent.STATUS_TEXT_CHANGED, result);
						hmiModel.notifyPropertyChange(ObservableEvent.LOCKRECORD_BUTTON_CHANGED, lockRecordButton.isSelected());
					}
					
				}.execute();
				
			}
		});
		
		buttonPanel.add(lockRecordButton);
		
		buttonPanel.add(Box.createHorizontalStrut(10));
		applyButton = new JButton("Apply");
		applyButton.setEnabled(false);
		applyButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				
				if (log.isLoggable(Level.INFO))
					log.log(Level.INFO, "Writing: '" + ownerTextField.getText() + "' to Database");
				
				new SwingWorker<String, Object>() {

					private String result;
					private String[] selectedFields = selectedRecord.getRecordFields();
					
					@Override
					protected String doInBackground() {
						try {
							basControl.updateRecord(selectedRecord.getRecordNumber(), 
									new String[]{selectedFields[0], selectedFields[1], 
								selectedFields[2], selectedFields[3], 
								selectedFields[4], ownerTextField.getText()});
							
							result = "Finished writing to Database.";
						} catch (RemoteException e1) {
							result = "Unable to update record: " + selectedRecord.getRecordNumber() +
							" . Cause: " + e1.getMessage();
						} catch (RecordNotFoundException e2) {
							result = "Unable to update record: " + selectedRecord.getRecordNumber() + 
							". Record does not exist. " + e2.getMessage();
						}
						return result;
					}

					@Override
					protected void done() {
						hmiModel.notifyPropertyChange(ObservableEvent.STATUS_TEXT_CHANGED, result);
					}
					
				}.execute();
								
			}
		});
		
		buttonPanel.add(applyButton);
		cancelButton = new JButton("Cancel");
		cancelButton.setEnabled(false);
		cancelButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				//if cancel button pressed, then put old owner value in textfield.
				if (selectedRecord != null) {
					ownerTextField.setText(selectedRecord.getRecordFields()[5]);
				}
			}
		});
		buttonPanel.add(cancelButton);

		bookRecordPanel.add(horizontalPanel);
		
		bookRecordPanel.add(buttonPanel);
		
	}
	/**
	 * Gets the presentation of the book panel.
	 * 
	 * @return the presentation of the book panel
	 */
	public JComponent getPresentation() {
		return bookRecordPanel;
	}
	
	
}
